/**
 * 项目名：五位一体化工安全信息平台
 * 日期：    2019-11-24 22:18:21
 * Copyright (c) 2015- joysuch-版权所有
 */

package com.joysuch.wwyt.risk.service.impl;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.itextpdf.text.Document;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfWriter;
import com.joysuch.wwyt.bp.enums.DataStateTypes;
import com.joysuch.wwyt.common.constant.Constant;
import com.joysuch.wwyt.common.entity.CommonIndexNotify;
import com.joysuch.wwyt.common.enums.CommonIndexNotifyTypes;
import com.joysuch.wwyt.common.repository.CommonIndexNotifyDao;
import com.joysuch.wwyt.core.common.ajax.ResultBean;
import com.joysuch.wwyt.core.common.util.DateTimeUtil;
import com.joysuch.wwyt.core.common.util.PageDataUtils;
import com.joysuch.wwyt.core.common.util.PageDataUtils.PageDataConvert;
import com.joysuch.wwyt.core.common.util.SimpleDateFormatCache;
import com.joysuch.wwyt.core.constant.Constants;
import com.joysuch.wwyt.core.enums.RiskLevels;
import com.joysuch.wwyt.core.support.Context;
import com.joysuch.wwyt.edu.enums.CertificateRemindTypes;
import com.joysuch.wwyt.mh.bean.MhMonitoringPointListBean;
import com.joysuch.wwyt.mh.entity.MhMonitoringPoint;
import com.joysuch.wwyt.mh.entity.MhMonitoringType;
import com.joysuch.wwyt.mh.repository.MhMonitoringPointDao;
import com.joysuch.wwyt.mh.repository.MhMonitoringTypeDao;
import com.joysuch.wwyt.risk.EvaluationPlanStrategies;
import com.joysuch.wwyt.risk.bean.*;
import com.joysuch.wwyt.risk.entity.*;
import com.joysuch.wwyt.risk.entity.dsl.QRiskDistrict;
import com.joysuch.wwyt.risk.entity.dsl.QRiskPoint;
import com.joysuch.wwyt.risk.enums.RiskPointStatus;
import com.joysuch.wwyt.risk.repository.*;
import com.joysuch.wwyt.risk.service.RiskEvaluationPlanService;
import com.joysuch.wwyt.util.StringUtil;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.BooleanExpression;
import javafx.util.Pair;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.shiro.util.Assert;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Order;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import javax.transaction.Transactional;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Transactional
public class RiskEvaluationPlanServiceImpl implements RiskEvaluationPlanService {

    @Autowired
    private RiskEvaluationPlanDao dao;
    @Autowired
    private RiskPointDao pointDao;
    @Autowired
    private RiskDistrictDao riskDistrictDao;
    @Autowired
    private MhMonitoringPointDao mhMonitoringPointDao;
    @Autowired
    private MhMonitoringTypeDao mhMonitoringTypeDao;
    @Autowired
    private RiskEvalPlanRemindDao riskEvalPlanRemindDao;
    @Autowired
    private CommonIndexNotifyDao commonIndexNotifyDao;
    @Autowired
    private RiskEvaluationBusinessDao businessDao;
    @Autowired
    private RiskEvaluationControlDao riskEvaluationControlDao;


    @Override
    public void add(RiskEvaluationPlan entity) throws Exception {
        dao.save(entity);
    }

    @Override
    public void update(RiskEvaluationPlan entity) throws Exception {
        RiskEvaluationPlan content = dao.findById(entity.getId()).get();
        if (content != null) {
            // TODO set nessessary properties
            dao.save(entity);
        }
    }

    @Override
    public Page<RiskEvaluationPlan> findByPage(Pageable page) {
        return dao.findAll(page);
    }

    @Override
    public void delete(Long id) {
        dao.deleteById(id);
    }

    @Override
    public void deleteByRiskPointId(Long riskPointId) {
        dao.deleteByRiskPointId(riskPointId);
    }

    @Override
    public RiskEvaluationPlan findById(Long id) {
        return dao.findById(id).get();
    }

    @Override
    public Page<RiskEvaluationPlanControlListBean> findByPage(Pageable page,
                                                              RiskEvaluationPlanControlListSearchBean condition) {
        QRiskPoint point = QRiskPoint.riskPoint;
        Predicate predicate = null;
        if (condition.getNameOrCode() != null) {
            predicate = ExpressionUtils.or(point.name.like("%" + condition.getNameOrCode() + "%"),
                    point.code.like("%" + condition.getNameOrCode() + "%"));
        }
        if (condition.getDistrictId() != null) {
            BooleanExpression eq = point.riskDistrict.id.eq(condition.getDistrictId());
            predicate = predicate == null ? eq : ExpressionUtils.and(predicate, eq);
        }
        if (condition.getRiskLevel() != null) {
            BooleanExpression eq = point.riskLevel.eq(condition.getRiskLevel());
            predicate = predicate == null ? eq : ExpressionUtils.and(predicate, eq);
        }
        if (condition.getVersionFlag() != null && condition.getVersionFlag().intValue() == 1) {
            BooleanExpression eq = point.status.eq(RiskPointStatus.AUDIT_SUCCESS.getIndex());
            predicate = predicate == null ? eq : ExpressionUtils.and(predicate, eq);
        }
        //去除风险点库数据 flag：shared=1
        //BooleanExpression ne = point.shared.ne(1);
        Predicate or = ExpressionUtils.or(point.shared.isNull(), point.shared.eq(0));
        predicate = predicate == null ? or : ExpressionUtils.and(predicate, or);

        Page<RiskPoint> all = predicate == null ? pointDao.findAll(page) : pointDao.findAll(predicate, page);

        return PageDataUtils.convertPageData(all, new PageDataConvert<RiskEvaluationPlanControlListBean, RiskPoint>() {

            @Override
            public RiskEvaluationPlanControlListBean convert(RiskPoint f) {
                RiskEvaluationPlanControlListBean b = new RiskEvaluationPlanControlListBean();
                b.setId(f.getId());
                b.setName(f.getName());
                b.setCode(f.getCode());
                if (f.getRiskDistrict() != null) {
                    b.setDistrictId(f.getRiskDistrict().getId());
                    b.setDistrictName(f.getRiskDistrict().getName());
                }
                RiskEvaluationPlan plan = dao.findFirstByRiskPointId(f.getId(), Sort.by(Order.desc("createTime")));
                if (plan != null) {
                    b.setEvaluationPeriod(plan.getPeriod());
                    b.setEvaluationPeriodUnit(plan.getIntervalUnit());
                    b.setEvaluationPlanId(plan.getId());
                    b.setEvaluationPeriodName(EvaluationPlanStrategies.findNameByCode(plan.getStrategy()));
                    if (plan.getNextEvaluationTime() != null) {
                        b.setNextEvaluationDate(SimpleDateFormatCache.getYmd().format(plan.getNextEvaluationTime()));
                    }
                    b.setStrategy(plan.getStrategy());
                }
                if (f.getLastEvaluationTime() != null) {
                    b.setLastEvaluationDate(SimpleDateFormatCache.getYmd().format(f.getLastEvaluationTime()));
                }
                b.setRiskLevel(f.getRiskLevel());
                b.setRiskLevelName(RiskLevels.findRiskLevelName(f.getRiskLevel()));
                return b;
            }
        });
    }

    /**
     * @param riskPointIdList 风险点id集合
     * @param strategies      评估计划策略
     * @param evaluationTime  评估时间
     * @param versionFlag     版本:null旧版本 1新版本(2.1.2版本 2021-02-02)
     */
    @Override
    public void batchMakePlan(List<Long> riskPointIdList, EvaluationPlanStrategies strategies, Date evaluationTime, Integer versionFlag) {
        Pair<Boolean, RiskEvalPlanRemind> controlNotify = needNotify(0);
        for (Long pointId : riskPointIdList) {
            RiskEvaluationPlan plan = new RiskEvaluationPlan();
            RiskEvaluationPlan oldPlan = dao.findFirstByRiskPointId(pointId, Sort.by(Order.desc("createTime")));
            if (oldPlan != null) {
                plan.setLastEvaluationTime(oldPlan.getLastEvaluationTime());
            }
            plan.setRiskPointId(pointId);
            plan.setStrategy(strategies.getCode());
            RiskPoint point = pointDao.getOne(plan.getRiskPointId());
            Date lastEvaluationTime = point.getLastEvaluationTime() == null ? new Date()
                    : point.getLastEvaluationTime();
            parseStrategies(strategies, plan, lastEvaluationTime, evaluationTime);

            RiskEvaluationPlan save = dao.save(plan);
            Long planId = save.getId();
            //通知判断,有通知配置+有分析人
            List<Long> analysts = null;
            if (versionFlag != null && versionFlag.intValue() == 1) {
                analysts = getNewAnalysts(point);
            } else {
                analysts = getAnalysts(point);
            }
            if (controlNotify.getKey() && !CollectionUtils.isEmpty(analysts)) {
                List<Long> collect = analysts.stream().distinct().collect(Collectors.toList());
                List<Long> notifyIds = Lists.newArrayList();
                for (Long analyst : collect) {
                    newNotifyControl(point, controlNotify, plan, notifyIds, analyst, planId);
                }
                plan.setNotifyIdJson(JSON.toJSONString(notifyIds));
                RiskPoint riskPoint = pointDao.findById(pointId).get();
                riskPoint.setNextEvaluationDate(plan.getNextEvaluationTime());
                pointDao.save(riskPoint);
                dao.save(plan);
            }
            removeNotify(oldPlan);
        }
    }

    private void removeNotify(RiskEvaluationPlan oldPlan) {
        if (oldPlan != null && oldPlan.getNotifyIdJson() != null) {
            List<Long> notifyIds = JSON.parseArray(oldPlan.getNotifyIdJson(), Long.class);
            List<CommonIndexNotify> list = commonIndexNotifyDao.findAllById(notifyIds);
            Iterator<CommonIndexNotify> iterator = list.iterator();
            while (iterator.hasNext()) {
                CommonIndexNotify next = iterator.next();
                if (next.getQueueOrNot() == 0) {
                    commonIndexNotifyDao.deleteById(next.getId());
                }
            }
        }
    }

    //flag:0 控制风险--风险点; 1 固有风险--风险区域
    private Pair<Boolean, RiskEvalPlanRemind> needNotify(Integer flag) {
        RiskEvalPlanRemind setting = getRemindSetting(flag);
        if (setting == null || setting.getExpireRemindOrNot() == 0) {
            return new Pair<>(false, null);
        }
        return new Pair<>(true, setting);
    }

    private List<Long> getAnalysts(RiskPoint riskPoint) {
        RiskPointEvaluationScl scl = riskPoint.getRiskPointEvaluationScl();
        RiskPointEvaluationJha jha = riskPoint.getRiskPointEvaluationJha();
        List<Long> userIds = Lists.newArrayList();
        if (scl != null) {
            userIds.add(scl.getBaseUser().getId());
        }
        if (jha != null) {
            userIds.add(jha.getBaseUser().getId());
        }
        return userIds;
    }

    private List<Long> getNewAnalysts(RiskPoint riskPoint) {
        String evaluatorIdJson = riskPoint.getEvaluatorIdJson();
        List<Long> collect = new ArrayList<>();
        if (StringUtils.isNotBlank(evaluatorIdJson)) {
            JSONObject evaluatorJson = JSON.parseObject(evaluatorIdJson);
            for (String str : evaluatorJson.keySet()) {
                final String json = evaluatorJson.get(str).toString();
                if (JSONUtil.isJsonArray(json)) {
                    JSONArray jsonArray = JSON.parseArray(json);
                    for (Object jsonObj : jsonArray) {
                        collect.add(Long.parseLong(jsonObj.toString()));
                    }
                } else {
                    collect.add(Long.parseLong(json));
                }
            }
        }
        return collect.stream().distinct().collect(Collectors.toList());
    }

    private void parseStrategies(EvaluationPlanStrategies strategies, RiskEvaluationPlan plan, Date lastEvaluationTime,
                                 Date evaluationTime) {

        Calendar c = Calendar.getInstance();
        c.setTime(lastEvaluationTime == null ? new Date() : lastEvaluationTime);
        if (strategies == EvaluationPlanStrategies.YEAR) {
            plan.setPeriod(1);
            plan.setIntervalUnit("year");
            c.add(Calendar.YEAR, 1);
            plan.setNextEvaluationTime(c.getTime());
        } else if (strategies == EvaluationPlanStrategies.HALF_YEAR) {
            plan.setPeriod(6);
            plan.setIntervalUnit("mon");
            c.add(Calendar.MONTH, 6);
            plan.setNextEvaluationTime(c.getTime());
        } else if (strategies == EvaluationPlanStrategies.SEASON) {
            plan.setPeriod(3);
            plan.setIntervalUnit("mon");
            c.add(Calendar.MONTH, 3);
            plan.setNextEvaluationTime(c.getTime());
        } else if (strategies == EvaluationPlanStrategies.MONTH) {
            plan.setPeriod(1);
            plan.setIntervalUnit("mon");
            c.add(Calendar.MONTH, 1);
            plan.setNextEvaluationTime(c.getTime());
        } else if (strategies == EvaluationPlanStrategies.WEEK) {
            plan.setPeriod(1);
            plan.setIntervalUnit("week");
            c.add(Calendar.WEEK_OF_YEAR, 1);
            plan.setNextEvaluationTime(c.getTime());
        } else if (strategies == EvaluationPlanStrategies.FIXED) {
            plan.setPeriod(1);
            plan.setIntervalUnit("week");
            plan.setNextEvaluationTime(evaluationTime);
        } else {
            // 发生改变时通知
        }
    }

    @Override
    public Page<RiskEvaluationPlanStableListBean> findDistrictStableRiskByPage(Pageable page,
                                                                               RiskEvaluationPlanStableListSearchBean search) {
        QRiskDistrict point = QRiskDistrict.riskDistrict;
        Predicate predicate = null;
        if (search.getNameOrCode() != null) {
            predicate = ExpressionUtils.or(point.name.like("%" + search.getNameOrCode() + "%"),
                    point.code.like("%" + search.getNameOrCode() + "%"));
        }
        predicate = ExpressionUtils.and(predicate, ExpressionUtils.or(point.state.notIn(DataStateTypes.DELETE.getState()), point.state.isNull()));
        if (search.getRiskLevel() != null) {
            BooleanExpression eq = point.riskLevel.eq(search.getRiskLevel());
            predicate = predicate == null ? eq : ExpressionUtils.and(predicate, eq);
        }
        //
        Page<RiskDistrict> all = predicate == null ? riskDistrictDao.findAll(page)
                : riskDistrictDao.findAll(predicate, page);
        return PageDataUtils.convertPageData(all,
                new PageDataConvert<RiskEvaluationPlanStableListBean, RiskDistrict>() {

                    @Override
                    public RiskEvaluationPlanStableListBean convert(RiskDistrict f) {
                        RiskEvaluationPlanStableListBean bean = new RiskEvaluationPlanStableListBean();
                        bean.setId(f.getId());
                        bean.setCode(f.getCode());
                        bean.setName(f.getName());
                        bean.setRiskLevel(f.getRiskLevel());
                        bean.setRiskLevelName(RiskLevels.findRiskLevelName(f.getRiskLevel()));
                        RiskEvaluationPlan plan = dao.findFirstByRiskDistrictId(f.getId(),
                                Sort.by(Order.desc("createTime")));
                        if (plan != null) {
                            bean.setEvaluationPeriod(plan.getPeriod());
                            bean.setEvaluationPeriodUnit(plan.getIntervalUnit());
                            bean.setEvaluationPlanId(plan.getId());
                            bean.setEvaluationPeriodName(EvaluationPlanStrategies.findNameByCode(plan.getStrategy()));
                            if (plan.getNextEvaluationTime() != null) {
                                bean.setNextEvaluationDate(
                                        SimpleDateFormatCache.getYmd().format(plan.getNextEvaluationTime()));
                            }
                            if (plan.getLastEvaluationTime() != null) {

                            }
                        }
                        //旧版本不用
                        RiskEvaluationBusiness reb = businessDao.findByRiskDistrictId(f.getId());
                        if (reb != null && reb.getEvaluationDate() != null) {
                            bean.setLastEvaluationDate(SimpleDateFormatCache.getYmd()
                                    .format(reb.getEvaluationDate()));
                        }

//                        if (f.getRiskDistrictEvaluation() != null) {
//                            Long eId = riskDistrictDao.getLastEvaluationId(f.getId());
//                            if (eId != null) {
//                                RiskDistrictEvaluation riskDistrictEvaluation = riskDistrictEvaluationDao.getOne(eId);
//                                if (riskDistrictEvaluation != null && riskDistrictEvaluation.getEvaluationTime() != null) {
//                                    bean.setLastEvaluationDate(SimpleDateFormatCache.getYmd()
//                                            .format(riskDistrictEvaluation.getEvaluationTime()));
//                                }
//                            }
//                        }
                        return bean;
                    }
                });
    }


    @Override
    public void batchSendEvaluationRemind(Long districtId, String districtName, Integer versionFlag) {
        List<Long> evaluatorIds = new ArrayList<>();
        if (versionFlag != null && versionFlag.equals(1)) {
            RiskEvaluationBusiness reb = businessDao.findByRiskDistrictId(districtId);
            if (reb != null) {
                evaluatorIds = StringUtil.covertJsonToLongList(reb.getEvaluationUserIds());
            }
        } else {
            Optional<RiskDistrict> optionalDistrict = riskDistrictDao.findById(districtId);
            if(optionalDistrict.isPresent()){
                RiskDistrictEvaluation evaluation = optionalDistrict.get().getRiskDistrictEvaluation();
                if (evaluation != null) {
                    evaluatorIds = Lists.newArrayList(evaluation.getEvaluationUserId());
                }
            }
        }
        if(!CollectionUtils.isEmpty(evaluatorIds)){
            LocalDate curDate = LocalDate.now();
            LocalDateTime curDateTime = LocalDateTime.now();
            List<CommonIndexNotify> notifyList = new ArrayList<>();
            for (Long userId : evaluatorIds) {
                CommonIndexNotify notify = new CommonIndexNotify();
                notify.setType(CommonIndexNotifyTypes.RISK_EVAL_PLAN_CONTROL.getType());
                notify.setReadFlag(0);
                notify.setQueueOrNot(0);
                notify.setRemindedOrNot(Constant.REMINDED_NOT);
                notify.setEduCertUserId(districtId);
                notify.setNotifyMessage(String.format(Constants.DISTRICT_CHANGE_NOTIFY_MESSAGE, districtName));
                notify.setRemindDate(curDate);
                notify.setRemindDateTime(curDateTime);
                notify.setUserId(userId);
                notifyList.add(notify);
            }
            commonIndexNotifyDao.saveAll(notifyList);
        }
    }

    /**
     * @param riskPointIdList 风区域id集合
     * @param strategies      评估计划策略
     * @param evaluationTime  评估时间
     * @param versionFlag     版本:null旧版本 1新版本(2.1.2版本 2021-02-02)
     */
    @Override
    public void batchMakeDistrictStableRiskPlan(List<Long> riskPointIdList, EvaluationPlanStrategies strategies,
                                                Date evaluationTime, Integer versionFlag) {
        Pair<Boolean, RiskEvalPlanRemind> stableNotify = needNotify(1);
        for (Long riskDistrictId : riskPointIdList) {
            RiskEvaluationPlan plan = new RiskEvaluationPlan();
            RiskEvaluationPlan oldPlan = dao.findFirstByRiskDistrictId(riskDistrictId, Sort.by(Order.desc("createTime")));
            if (oldPlan != null) {
                plan.setLastEvaluationTime(oldPlan.getLastEvaluationTime());
            }
            // 此处是设置风险分区ID
            plan.setRiskDistrictId(riskDistrictId);
            plan.setStrategy(strategies.getCode());
            RiskDistrict district = riskDistrictDao.findById(riskDistrictId).get();
            Date lastEvaluationTime = null;
            List<Long> evaluatorIds = new ArrayList<>();
            if (versionFlag != null && versionFlag.intValue() == 1) {
                RiskEvaluationBusiness reb = businessDao.findByRiskDistrictId(riskDistrictId);
                if (reb != null) {
                    lastEvaluationTime = reb.getEvaluationDate();
                    evaluatorIds = StringUtil.covertJsonToLongList(reb.getEvaluationUserIds());
                }
            } else {
                RiskDistrictEvaluation evaluation = district.getRiskDistrictEvaluation();
                if (evaluation != null) {
                    evaluatorIds = Lists.newArrayList(evaluation.getEvaluationUserId());
                    lastEvaluationTime = evaluation.getEvaluationTime();
                }
            }
            parseStrategies(strategies, plan, lastEvaluationTime, evaluationTime);
            RiskEvaluationPlan save = dao.save(plan);
            Long planId = save.getId();
            //通知判断,有通知配置+有评估人
            if (stableNotify.getKey() && !org.springframework.util.CollectionUtils.isEmpty(evaluatorIds)) {
                List<CommonIndexNotify> indexNotifys = newNotifyStable(stableNotify, plan, evaluatorIds, CommonIndexNotifyTypes.RISK_EVAL_PLAN_STABLE, planId, "风险区域'", district.getName());
                if (!CollectionUtils.isEmpty(indexNotifys)) {
                    List<Long> notifyIds = indexNotifys.stream().map(CommonIndexNotify::getId).collect(Collectors.toList());
                    plan.setNotifyIdJson(JSONArray.toJSONString(notifyIds));
                }
                //保存下一次评估时间
                district.setNextEvaluationDate(plan.getNextEvaluationTime());
                riskDistrictDao.save(district);
                dao.save(plan);
            }
            //之前的未加入队列的计划删除，已经加入的无需cancel
            //包括提醒配置从是变成否，也不需要对之前的计划通知做任何调整
            removeNotify(oldPlan);
        }
    }

    @Override
    public void districtReCal(RiskDistrict district, Date evaluationTime, Integer versionFlag) {
        Pair<Boolean, RiskEvalPlanRemind> stableNotify = needNotify(1);
        //计算下次计划时间
        RiskEvaluationPlan plan = dao.findFirstByRiskDistrictId(district.getId(), Sort.by(Order.desc("createTime")));
        if (plan == null) {
            return;
        }
        String notifyIdJson = plan.getNotifyIdJson();
        Date nextEvaluationTime = plan.getNextEvaluationTime();
        boolean evalBeforeNeed = !evaluationTime.after(nextEvaluationTime);
        String strategy = plan.getStrategy();
        if (strategy.equals(EvaluationPlanStrategies.FIXED.getCode())) {
            parseStrategies(EvaluationPlanStrategies.findByCode(strategy), plan, evaluationTime, plan.getNextEvaluationTime());
        } else {
            parseStrategies(EvaluationPlanStrategies.findByCode(strategy), plan, evaluationTime, null);
        }
        dao.save(plan);
        List<Long> evaluatorIds = null;
        RiskEvaluationControl cor = riskEvaluationControlDao.findByName("区域固有风险评价");
        if (versionFlag != null && versionFlag.intValue() == 1) {
            //新版区域固有风险评估关闭 不更新通知
            if (cor != null && cor.getSwitchState() != null && cor.getSwitchState().intValue() == 1) {
                RiskEvaluationBusiness reb = businessDao.findByRiskDistrictId(district.getId());
                if (reb != null) {
                    evaluatorIds = StringUtil.covertJsonToLongList(reb.getEvaluationUserIds());
                }
            }
        } else {
            RiskDistrictEvaluation evaluation = district.getRiskDistrictEvaluation();
            if (evaluation != null) {
                evaluatorIds = Lists.newArrayList(evaluation.getEvaluationUserId());
            }
        }
        //通知判断,有通知配置+有评估人
        if (stableNotify.getKey() && !org.springframework.util.CollectionUtils.isEmpty(evaluatorIds)) {
            List<CommonIndexNotify> indexNotifys = newNotifyStable(stableNotify, plan, evaluatorIds, CommonIndexNotifyTypes.RISK_EVAL_PLAN_STABLE, plan.getId(), "风险区域'", district.getName());
            if (org.springframework.util.CollectionUtils.isEmpty(indexNotifys)) {
                List<Long> notifyIds = indexNotifys.stream().map(CommonIndexNotify::getId).collect(Collectors.toList());
                plan.setNotifyIdJson(JSON.toJSONString(notifyIds));
            }
            district.setNextEvaluationDate(plan.getNextEvaluationTime());
            riskDistrictDao.save(district);
            dao.save(plan);
        }
        //通知表相关数据清除
        removeNotify(notifyIdJson, evalBeforeNeed);
    }

    private List<CommonIndexNotify> newNotifyStable(Pair<Boolean, RiskEvalPlanRemind> stableNotify, RiskEvaluationPlan plan, List<Long> evaluationUserIds, CommonIndexNotifyTypes riskEvalPlanStable, Long id, String s, String name) {
        List<CommonIndexNotify> notifyList = new ArrayList<>();
        for (Long evaluationUserId : evaluationUserIds) {
            CommonIndexNotify notify = new CommonIndexNotify();
            String format = calNotifyDate(stableNotify, plan, notify);
            notify.setUserId(evaluationUserId);
            notify.setType(riskEvalPlanStable.getType());
            notify.setEduCertUserId(id);
            notify.setNotifyMessage(s + name + "'评估计划" + format + "即将到期");
            notifyList.add(notify);
        }
        if (!CollectionUtils.isEmpty(notifyList)) {
            commonIndexNotifyDao.saveAll(notifyList);
        }
        return notifyList;
    }

    private void removeNotify(String notifyIdJson, boolean evalBeforeNeed) {
        if (notifyIdJson != null && evalBeforeNeed) {
            List<Long> longs = JSON.parseArray(notifyIdJson, Long.class);
            List<CommonIndexNotify> list = commonIndexNotifyDao.findAllById(longs);
            for (CommonIndexNotify notify : list) {
                if (notify.getQueueOrNot() == 0) {
                    commonIndexNotifyDao.deleteById(notify.getId());
                }
            }
        }
    }

    @Override
    public void riskPointReCal(RiskPoint riskPoint, Date evaluationTime, Integer versionFlag) {
        Pair<Boolean, RiskEvalPlanRemind> controlNotify = needNotify(0);
        //计算下次计划时间
        RiskEvaluationPlan plan = dao.findFirstByRiskPointId(riskPoint.getId(), Sort.by(Order.desc("createTime")));
        if (plan == null) {
            return;
        }
        String notifyIdJson = plan.getNotifyIdJson();
        Date nextEvaluationTime = plan.getNextEvaluationTime();
        boolean evalBeforeNeed = !evaluationTime.after(nextEvaluationTime);
        String strategy = plan.getStrategy();
        if (strategy.equals(EvaluationPlanStrategies.FIXED.getCode())) {
            parseStrategies(EvaluationPlanStrategies.findByCode(strategy), plan, evaluationTime, plan.getNextEvaluationTime());
        } else {
            parseStrategies(EvaluationPlanStrategies.findByCode(strategy), plan, evaluationTime, null);
        }
        RiskEvaluationPlan save = dao.save(plan);
        //通知判断,有通知配置+有分析人
        List<Long> analysts = null;
        if (versionFlag != null && versionFlag.intValue() == 1) {
            analysts = getNewAnalysts(riskPoint);
        } else {
            analysts = getAnalysts(riskPoint);
        }
        if (controlNotify.getKey() && !CollectionUtils.isEmpty(analysts)) {
            List<Long> collect = analysts.stream().distinct().collect(Collectors.toList());
            List<Long> notifyIds = Lists.newArrayList();
            for (Long analyst : collect) {
                newNotifyControl(riskPoint, controlNotify, plan, notifyIds, analyst, save.getId());
            }
            plan.setNotifyIdJson(JSON.toJSONString(notifyIds));
            riskPoint.setNextEvaluationDate(plan.getNextEvaluationTime());
            pointDao.save(riskPoint);
            dao.save(plan);
        }
        //通知表相关数据清除
        removeNotify(notifyIdJson, evalBeforeNeed);
    }


    @Override
    public int riskPointBatchReCal(List<RiskPointBatchEvaluationBean> batchEvaluations) {

        List<RiskPoint> riskPoints = new ArrayList<>();
        List<RiskEvaluationPlan> plans = new ArrayList<>();
        //是否通知
        Pair<Boolean, RiskEvalPlanRemind> controlNotify = needNotify(0);
        //批量获取风险点评估计划
        Set<Long> pointIds = batchEvaluations.stream().map(RiskPointBatchEvaluationBean::getRiskPoint).map(RiskPoint::getId).collect(Collectors.toSet());

        Map<Long, RiskEvaluationPlan> planMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(pointIds)) {
            List<RiskEvaluationPlan> lastPlanList = dao.findLastPlanByPointIds(pointIds);
            planMap = lastPlanList.stream().collect(Collectors.toMap(RiskEvaluationPlan::getRiskPointId, Function.identity()));
        }

        for (RiskPointBatchEvaluationBean each : batchEvaluations) {
            RiskPoint riskPoint = each.getRiskPoint();
            Date evaluationTime = each.getEvaluationTime();
            //下次计划
            RiskEvaluationPlan plan = planMap.get(riskPoint.getId());
            if (plan != null) {
                String notifyIdJson = plan.getNotifyIdJson();
                Date nextEvaluationTime = plan.getNextEvaluationTime();
                boolean evalBeforeNeed = !evaluationTime.after(nextEvaluationTime);
                String strategy = plan.getStrategy();
                if (strategy.equals(EvaluationPlanStrategies.FIXED.getCode())) {
                    parseStrategies(EvaluationPlanStrategies.findByCode(strategy), plan, evaluationTime, plan.getNextEvaluationTime());
                } else {
                    parseStrategies(EvaluationPlanStrategies.findByCode(strategy), plan, evaluationTime, null);
                }
                //通知判断,有通知配置+有分析人
                List<Long> analysts = getNewAnalysts(riskPoint);
                if (controlNotify.getKey() && !CollectionUtils.isEmpty(analysts)) {
                    List<Long> collect = analysts.stream().distinct().collect(Collectors.toList());
                    List<Long> notifyIds = Lists.newArrayList();
                    for (Long analyst : collect) {
                        newNotifyControl(riskPoint, controlNotify, plan, notifyIds, analyst, plan.getId());
                    }
                    plan.setNotifyIdJson(JSON.toJSONString(notifyIds));
                    riskPoint.setNextEvaluationDate(plan.getNextEvaluationTime());
                    riskPoints.add(riskPoint);
                    plans.add(plan);

                }
                //通知表相关数据清除
                removeNotify(notifyIdJson, evalBeforeNeed);
            }
        }
        if (!CollectionUtils.isEmpty(riskPoints)) {
            pointDao.saveAll(riskPoints);
        }
        if (!CollectionUtils.isEmpty(plans)) {
            dao.saveAll(plans);
        }
        return riskPoints.size();
    }

    private void newNotifyControl(RiskPoint riskPoint, Pair<Boolean, RiskEvalPlanRemind> controlNotify, RiskEvaluationPlan plan, List<Long> notifyIds, Long analyst, Long id) {
        CommonIndexNotify notify = new CommonIndexNotify();
        String format = calNotifyDate(controlNotify, plan, notify);
        notify.setUserId(analyst);
        notify.setType(CommonIndexNotifyTypes.RISK_EVAL_PLAN_CONTROL.getType());
        notify.setEduCertUserId(id);
        notify.setNotifyMessage("风险点'" + riskPoint.getName() + "'评估计划" + format + "即将到期");
        CommonIndexNotify indexNotify = commonIndexNotifyDao.save(notify);
        notifyIds.add(indexNotify.getId());
    }

    private String calNotifyDate(Pair<Boolean, RiskEvalPlanRemind> stableNotify, RiskEvaluationPlan plan, CommonIndexNotify notify) {
        RiskEvalPlanRemind remind = stableNotify.getValue();
        Integer days = CertificateRemindTypes.getDays(remind.getRemindType());
        LocalTime remindTime = remind.getRemindTime();
        Date nextEvaluationTime = plan.getNextEvaluationTime();
        LocalDateTime nextEvalTime = DateTimeUtil.date2LocalDateTime(nextEvaluationTime);
        String format = nextEvalTime.format(DateTimeFormatter.ofPattern("MM月dd日"));
        LocalDateTime needDate = nextEvalTime.minusDays(days);
        LocalDateTime needDateTime = LocalDateTime.of(needDate.toLocalDate(), remindTime);
        notify.setRemindDate(needDate.toLocalDate());
        notify.setRemindDateTime(needDateTime);
        return format;
    }

    // 导出
    @Override
    public void list(Pageable page, RiskEvaluationPlanControlListSearchBean condition) throws Exception {
        Page<RiskPoint> all = pointDao.findAll(page);
        // List<RiskPoint> all = pointDao.findAll();
        List<RiskEvaluationPlanControlListBean> list = new ArrayList<RiskEvaluationPlanControlListBean>();
        Workbook workbook = null;
        for (RiskPoint riskPoint : all) {
            RiskEvaluationPlanControlListBean converts = converts(riskPoint);
            list.add(converts);
        }
        workbook = ExcelExportUtil.exportExcel(new ExportParams("风险控制", "风险控制"),
                RiskEvaluationPlanControlListBean.class, list);
        File savefile = new File("D:/excel/");
        if (!savefile.exists()) {
            savefile.mkdirs();
        }
        FileOutputStream fos = new FileOutputStream("D:/excel/风险控制数据.xlsx");
        workbook.write(fos);
        fos.close();
    }

    private static boolean fileExist(String filePath) {
        boolean flag = false;
        try {
            File file = new File(filePath);
            flag = file.exists();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }

    private RiskEvaluationPlanControlListBean converts(RiskPoint f) {
        RiskEvaluationPlanControlListBean b = new RiskEvaluationPlanControlListBean();
        b.setId(f.getId());
        b.setName(f.getName());
        b.setCode(f.getCode());
        if (f.getRiskDistrict() != null) {
            b.setDistrictId(f.getRiskDistrict().getId());
            b.setDistrictName(f.getRiskDistrict().getName());
        }
        RiskEvaluationPlan plan = dao.findFirstByRiskPointId(f.getId(), Sort.by(Order.desc("createTime")));
        if (plan != null) {
            b.setEvaluationPeriod(plan.getPeriod());
            b.setEvaluationPeriodUnit(plan.getIntervalUnit());
            b.setEvaluationPlanId(plan.getId());
            b.setEvaluationPeriodName(EvaluationPlanStrategies.findNameByCode(plan.getStrategy()));
            if (plan.getNextEvaluationTime() != null) {
                b.setNextEvaluationDate(SimpleDateFormatCache.getYmd().format(plan.getNextEvaluationTime()));
            }
        }
        if (f.getLastEvaluationTime() != null) {
            b.setLastEvaluationDate(SimpleDateFormatCache.getYmd().format(f.getLastEvaluationTime()));
        }
        b.setRiskLevel(f.getRiskLevel());
        b.setRiskLevelName(RiskLevels.findRiskLevelName(f.getRiskLevel()));
        return b;
    }

    // 模板下载
    public void download(HttpServletResponse response) throws Exception {
        Workbook workbook = null;
        ArrayList<MhMonitoringPointListBean> list = new ArrayList<>();
        workbook = ExcelExportUtil.exportExcel(new ExportParams(), MhMonitoringPointListBean.class, list);
        File savefile = new File("D:/excel/");
        if (!savefile.exists()) {
            savefile.mkdirs();
        }
        FileOutputStream fos = new FileOutputStream("D:/excel/jiancedian.xlsx");
        workbook.write(fos);
        fos.close();

    }

    // 上传模板
    public void uploading(MultipartFile file) throws Exception {
        ImportParams params = new ImportParams();
        params.setTitleRows(0);
        params.setHeadRows(1);
        // 校验是不是正确的Excel
        // params.setImportFields();
        List<MhMonitoringPointListBean> list = ExcelImportUtil.importExcel(file.getInputStream(),
                MhMonitoringPointListBean.class, params);
        System.out.println(list.size());

        for (MhMonitoringPointListBean m : list) {
            System.out.println(m);
            MhMonitoringPoint h = new MhMonitoringPoint();
            h.setName(m.getName());// 监测点名称
            h.setUnit(m.getUnit());// 监测点单位
            h.setPointCode(m.getPointCode());// 监测点编号
            h.setLowValue1(m.getLowValue1() + 0.0);// 一级报警阀值B
            h.setLowValue2(m.getLowValue2() + 0.0);// 一级报警阀值A
            h.setHighValue1(m.getHighValue1() + 0.0);// 二级报警阀值B
            h.setHighValue2(m.getHighValue2() + 0.0);// 二级报警阀值A
            h.setTenentId(Context.getCurrentTenantId());
            h.setOrgCode(Context.getCompanyCode());
            MhMonitoringType one = mhMonitoringTypeDao.getOne(new Long(77));
            h.setMhMonitoringType(one);
            System.out.println("这是监测点===" + h);
            mhMonitoringPointDao.save(h);
        }
    }

    // 打印
    @Override
    public void print(Pageable pageable) {
        try {
            Document document = new Document();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("D:/excel/test.pdf"));
            // 添加一个页面
            // PdfWriter.getInstance(document,baos );
            document.open();
            Page<RiskPoint> all = pointDao.findAll(pageable);
            document.add(new Paragraph("测试打印"));

            document.close();
            writer.close();
            byte[] content = baos.toByteArray();

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    @Override
    public ResultBean remindSettingSave(Integer flag, RiskEvalPlanRemindBean bean) {
        Long id = bean.getId();
        Integer expireRemindOrNot = bean.getExpireRemindOrNot();
        String remindType = bean.getRemindType();
        LocalTime remindTime = bean.getRemindTime();
        RiskEvalPlanRemind remind;
        if (id == null) {
            RiskEvalPlanRemind first = riskEvalPlanRemindDao.findFirstByRiskEvalTypeAndState(flag, DataStateTypes.EFFECTIVE.getState());
            if (first != null) {
                return ResultBean.fail(101, "此类型配置已存在");
            }
            remind = new RiskEvalPlanRemind();
            remind.setRiskEvalType(flag);
            remind.setState(DataStateTypes.EFFECTIVE.getState());
        } else {
            remind = riskEvalPlanRemindDao.findById(id).orElseThrow(() -> new IllegalArgumentException("数据不存在"));
            if (DataStateTypes.UN_EFFECTIVE.equals(remind.getState())) {
                return ResultBean.fail(101, "此数据已作废");
            }
        }
        if (expireRemindOrNot == 1) {
            Assert.notNull(remindType, "请选择提醒类型");
            Assert.notNull(remindTime, "请选择提醒时间");
            Assert.notNull(CertificateRemindTypes.getHours(remindType), "不支持此提醒类型");
        }
        BeanUtils.copyProperties(bean, remind);
        riskEvalPlanRemindDao.save(remind);
        return ResultBean.defaultSuccessResult();
    }

    @Override
    public ResultBean remindSettingGet(Integer flag) {
        return ResultBean.success(getRemindSetting(flag));
    }

    public RiskEvalPlanRemind getRemindSetting(Integer flag) {
        RiskEvalPlanRemind first = riskEvalPlanRemindDao.findFirstByRiskEvalTypeAndState(flag, DataStateTypes.EFFECTIVE.getState());
        return first;
    }

}
